package com.project.restaurant;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
import com.baomidou.mybatisplus.generator.config.GlobalConfig;
import com.baomidou.mybatisplus.generator.config.PackageConfig;
import com.baomidou.mybatisplus.generator.config.StrategyConfig;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.zaxxer.hikari.HikariDataSource;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.jdbc.ScriptRunner;

import java.nio.charset.Charset;
import java.sql.Connection;

/**
 * 发现代码生成器生成的外键，是对应数据库的字段和类型
 * 而不是生成外键对应的类
 */
public class CodeGenerator {
    /**
     * 数据源配置
     */
    private static DataSourceConfig DATA_SOURCE_CONFIG=null;
    static {
        HikariDataSource dataSource = new HikariDataSource();
        dataSource.setUsername("root");
        dataSource.setPassword("123123");
        dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
        dataSource.setJdbcUrl("jdbc:mysql://127.0.0.1:3306/lsl?useSSL=false&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&tinyInt1isBit=false&allowMultiQueries=true&serverTimezone=GMT%2B8");
        DataSourceConfig dataSourceConfig = new DataSourceConfig.Builder(dataSource)
                .build();
        DATA_SOURCE_CONFIG=dataSourceConfig;
    }

    public static void main(String[] args) throws Exception {
//        initMysql("db/electricity_shop.sql","UTF-8");
        codeGenerator();
    }

    /**
     * 数据库初始化。执行sql文件生成对应的数据库表和数据
     * @param sqlFilePath sql文件的所在相对路径，相对与classpath://
     * @param sqlCharset 读取该sql文件时，用的文件编码
     * @throws Exception
     */
    private static void initMysql(String sqlFilePath,String sqlCharset) throws Exception {
        Connection conn = DATA_SOURCE_CONFIG.getConn();
        //设置读取文件时的文件编码为UTF-8,注意sql文件的编码和连接的编码一致
        Resources.setCharset(Charset.forName(sqlCharset));
        //创建一个脚本执行器
        ScriptRunner scriptRunner = new ScriptRunner(conn);
        //设置为执行任务自动提交
        scriptRunner.setAutoCommit(true);
        //执行脚本
        scriptRunner.runScript(Resources.getResourceAsReader(sqlFilePath));
        conn.close();
    }

    /**
     * 代码的自动生成
     */
    private static void codeGenerator(){
        //创建一个代码自动生成器
        AutoGenerator autoGenerator = new AutoGenerator(DATA_SOURCE_CONFIG);
        //设置全局配置信息
        autoGenerator.global(globalConfig().build())
                //设置策略信息
                .strategy(strategyConfig().build())
                //设置包配置信息
                .packageInfo(packageConfig().build())
                //进行代码生成
                .execute();
    }

    /**
     * 策略配置
     */
    private static StrategyConfig.Builder strategyConfig() {
        StrategyConfig.Builder builder = new StrategyConfig.Builder();
        // 设置需要生成对应代码的表名。允许使用正则表达式。
        builder.addInclude("demo","demo_relation","role")
//                //添加表前缀过滤。只要匹配其中一个就会被设置过滤
//                .addTablePrefix()
//                //添加表后缀过滤
//                .addTableSuffix()
                //.addExclude()不生成对应代码的表名
                //生成的service服务接口
                .serviceBuilder()
                    .formatServiceFileName("%sService")
                //生成实体类
                .entityBuilder()
                    //数据库表映射到实体的命名策略
                    .naming(NamingStrategy.underline_to_camel)
                    //表字段映射到实体类属性的命名策略。下划线转驼峰命名
                    .columnNaming(NamingStrategy.underline_to_camel)
                    //开启 ActiveRecord 模式。
//                    .enableActiveRecord()
                    //开启链式模型。就是set方法返回this对象
                    .enableChainModel()
                    //使用lombok模型
                    .enableLombok()
                    //设置主键生成策略。如果数据库表是主键自动增长的话，那么生成主键会带有IdType.AUTO
                    .idType(IdType.ASSIGN_ID)
                    //哪个数据库字段是逻辑删除
                    .logicDeleteColumnName("is_deleted")
                    //实体类的逻辑删除属性
                    .logicDeletePropertyName("isDeleted")
                    //哪个数据库字段是乐观锁字段
                    .versionColumnName("version")
                    //实体类的乐观锁字段
                    .versionPropertyName("version");
        return builder;
    }
    /**
     * 全局配置
     */
    private static GlobalConfig.Builder globalConfig() {
        GlobalConfig.Builder builder = new GlobalConfig.Builder();
        //设置文件可以被覆盖
        builder.fileOverride()
                //设置生成的路径。内部源码是用new File的
                .outputDir("D:\\Temp");
        return builder;
    }

    /**
     * 包配置
     */
    private static PackageConfig.Builder packageConfig() {
        PackageConfig.Builder builder = new PackageConfig.Builder();
        builder.parent("com.boot_web")
                .entity("bean");
        return builder;
    }

}
